#include "TcpServer.hpp"
#include "Service.hpp"
#include "searcher.hpp"
#include "log.hpp"
#include "util.hpp"
#include <memory>

// 去标签化后的文档路径
const std::string input = "data/raw_html/raw.txt";
// 服务器获取图标请求
const std::string favicon = "./wwwroot/favicon.ico";

// 创建搜索的对象, 并初始化
ns_searcher::Searcher searcher;

// 提示启动服务器方法
static void Usage(std::string process)
{
    std::cerr << "\nUsage: " << process << " port\n" << std::endl;
}

// 处理客户端请求, 进行服务器响应
int BeginHandler(Connection *conn, std::string &message, service_t service)
{
    // 1. 获取请求
    Request req;
    // 解析请求
    if(!Parser(message, &req))
    {
        // 解析失败
        return -1;
        LogMessage(FATAL, "Parse req error");
    }
    std::cout << "请求的信息: " << req.path << std::endl;
    LogMessage(DEBUG, "解析完成");

    // 2. 发送响应
    Response resp = service(req, searcher);
    LogMessage(DEBUG, "获得响应");

    // 发送的是获取主页面请求
    if(req.path == default_root_path) conn->outbuffer_ = resp.html_string;
    // 服务器有时会自动请求favicon.ico, 想获得图标, 这里拒绝该请求, 直接返回响应
    else if(req.path == favicon) conn->outbuffer_ = "404 Not Found";
    // 发送的是搜索请求
    else conn->outbuffer_ = resp.json_string;
    
    // 调用响应回调
    conn->sender_(conn);

    // 3. 修改读写
    // 判断需要打开或者关闭读和写(不同事件不同)
    if(conn->outbuffer_.empty()) conn->R_->EnableReadWrite(conn->sock_, true, false);
    else conn->R_->EnableReadWrite(conn->sock_, true, true);

    LogMessage(INFO, "------------ 这个业务处理完成 ------------");

    return 0;
}

int HandlerRequest(Connection *conn, std::string &message)
{
    // 开始调用业务处理函数
    return BeginHandler(conn, message, SearchResult);
}

int main(int argc, char *argv[])
{
    // 判断是否正确运行服务器
    if(argc != 2)
    {
        Usage(argv[0]);
        exit(0);
    }

    // 将日志重定向到日志文件中
    Log *log = Log::GetInstance();
    log->enable();
    
    LogMessage(INFO, "服务器启动成功...");
    
    // 使用智能指针创建, 自动管理内存
    std::unique_ptr<TcpServer> svr(new TcpServer(HandlerRequest, atoi(argv[1])));
    // 初始化搜索引擎(包括创建索引, 添加竞价排名等)
    searcher.InitSearcher(input);
    // 运行服务器
    svr->Run();

    return 0;
}



// 调用cpp-httplib版

// #include "cpp-httplib/httplib.h"
// #include "searcher.hpp"
// #include "log.hpp"
// #include "util.hpp"

// // 去标签化后的文档路径
// const std::string input = "data/raw_html/raw.txt";
// // 服务器获取图标请求
// const std::string root_path = "./wwwroot";

// int main()
// {
//     // 将日志重定向到日志文件中
//     // Log *log = Log::GetInstance();
//     // log->enable();

//     // 创建搜索的对象, 并初始化
//     ns_searcher::Searcher search;
//     search.InitSearcher(input);

//     // 使用httplib库, 创建httplib对象svr
//     httplib::Server svr;
//     // 设置服务器的根目录是root_path
//     svr.set_base_dir(root_path.c_str());
//     // 调用Get方法, 定义一个GET请求处理函数
//     svr.Get("/s", [&search](const httplib::Request &req, httplib::Response &rsp){
//             // 检查req中是否含有word参数(例如:http://example.com/s?word=hello)
//             if(!req.has_param("word"))
//             {
//                 // 服务器返回给客户端数据
//                 // 如果没有word参数, 响应对应的内容，响应的内容类型为 text/plain(纯文本数据), 并使用uft-8编码
//                 rsp.set_content("必须要有搜索关键字!", "text/plain; charset=utf-8");
//                 return;
//             }
//             // 获取HTTP请求中word参数的值(在上面的例子中, 这个word参数的值就是hello)
//             std::string word = req.get_param_value("word");
//             LogMessage(INFO, "用户在搜索: %s", word.c_str());

//             std::string json_string;
//             // 调用Search根据word查找到对应的内容, 并存储到json_string中(这里存储的Json格式的内容)
//             search.Search(word, &json_string);
//             // json_string是响应的内容，响应的类型为 application/json(Json格式的数据)
//             // 这里因为json_string存储的是Json格式的数据, 所以响应给客户端的数据的格式为Json
//             rsp.set_content(json_string, "application/json");
//             });
//     LogMessage(INFO, "服务器启动成功...");
//     // 启动服务器, 监听指定的IP地址(0.0.0.0表示监听所有可用的网络接口[包括本地主机和外部网络])和端口
//     svr.listen("0.0.0.0", 8081);

//     return 0;
// }
